Rust Borrowing (& and &mut)

Reference(&) means same this as borrowing in Rust.
Rust avoids all these problems.
Rust track lifetimes of all references to ensure they live long enough

Problem A: Dangling References (Memory Corruption)

Dangling References allowed in C++
int& get_dangling_reference() {
    int x = 42;
    return x;           // 'x' is destroyed here when function ends.
}

int main() {
    int& ref = get_dangling_reference();
    cout << ref ;           // Runtime crash. Compile time ok
    return 0;
}
    
Not allowed Rust
fn get_dangling_reference() -> &i32 {
    let x = 42;
    &x                          // ❌ COMPILE ERROR
}
fn main() {
    let ref_val = get_dangling_reference();
}
                    

How it works? Rust compiler's Borrow Checker makes sure that reference never outlive the data it points to.

Problem B: Concurrent Mutation (Allowed in C++ not Rust)

C++. Reference is mutable by default
int main() {
    int a = 10;
    int &b = a;  // Reference mutable by default
    b = 2;       // Reference changed
    std::cout << a;
}
$ g++ main.cpp
2
                
Rust
References are immutable by default
fn main() {
    let a = 10;
    let b = &a;
    b = 2;          // Compiler Error
    println!("b={}",b);
}
$ cargo run
10
                

References are made MUTABLE explicitly
fn main() {
    let mut a = 'A';
    let b:&mut char = &mut a;
    *b = 'B';
    println!("{}", *b);
}
$ cargo run
B
                
We can have any number of immutable borrows (&T) at a time OR
We can have exactly 1 mutable borrow (&mut T) at a time.
We cannot mix them.
Using Aliasing XOR Mutability rule
fn main() {
    let mut numbers = vec![1, 2, 3];

    let first = &numbers[0];            // IMMUTABLE borrow (&). Ok

    // MUTABLY borrow (&mut) numbers to push an item
    numbers.push(4); // ❌ COMPILE ERROR: cannot borrow `numbers` as mutable 
                     // because it is also borrowed as immutable (`first`)
}